package iks.utils.geom
{
	import flash.display.Graphics;
	
	/**
	 * 2D vector class
	 * @author StefanieKaka
	 */
	public final class Vector2D 
	{
		/**
		 * 计算两个向量间的角度
		 * @param	vec1 向量1
		 * @param	vec2 向量2
		 * @return 两个向量间的角度
		 */
		public static function angleBetween(vec1 : Vector2D, vec2 : Vector2D) : Number
		{
			if (!vec1.isNormalized())
				vec1 = vec1.clone().normalize();
				
			if (!vec2.isNormalized())
				vec2 = vec2.clone().normalize();
				
			return Math.acos(vec1.dotProduct(vec2));
		}
		
		/**
		 * 构造函数
		 */
		public function Vector2D(x : Number = 0, y : Number = 0) 
		{
			m_x = x;
			m_y = y;
		}
		
		/**
		 * 克隆一个新的Vector2D对象
		 */
		public function clone() : Vector2D
		{
			return new Vector2D(m_x, m_y);
		}
		
		/**
		 * x, y归0
		 */
		public function zeroVector() : Vector2D
		{
			m_x = 0;
			m_y = 0;
			return this;
		}
		
		/**
		 * 判断是否是0向量
		 */
		public function isZero() : Boolean
		{
			return m_x == 0 && m_y == 0;
		}
		
		/**
		 * 判断向量的长度是否为1.0
		 */
		public function isNormalized() : Boolean
		{
			return length == 1.0;
		}
		
		/**
		 * 判断两个向量是否相等
		 */
		public function equals(vector2 : Vector2D) : Boolean
		{
			return m_x == vector2.x && m_y == vector2.y;
		}
		
		/**
		 * 设置向量的长度, 但是角度不变
		 */
		public function set length(value : Number) : void
		{
			var ang : Number = this.angle;
			m_x = Math.cos(ang) * value;
			m_y = Math.sin(ang) * value;
			
			if (Math.abs(m_x) <= 0.00000001)
				m_x = 0;
				
			if (Math.abs(m_y) <= 0.00000001)
				m_y = 0;
		}
		
		/**
		 * 获得向量的长度
		 */
		public function get length() : Number
		{
			return Math.sqrt(lengthSquared);
		}
		
		/**
		 * 得到向量长度的平方, 方便快速的计算
		 */
		public function get lengthSquared() : Number
		{
			return m_x * m_x + m_y * m_y;
		}
		
		/**
		 * 向量的角度将会改变, 但是长度不变
		 */
		public function set angle(value : Number) : void
		{
			var len : Number = length;
			m_x = Math.cos(value) * len;
			m_y = Math.sin(value) * len;
		}
		
		/**
		 * 获得向量的角度
		 */
		public function get angle() : Number
		{
			return Math.atan2(m_y, m_x);
		}
		
		/**
		 * 使向量标准化
		 */
		public function normalize() : Vector2D
		{
			if (length == 0)
			{
				m_x = 1;
				return this;
			}
			
			var len : Number = length;
			m_x /= len;
			m_y /= len;
			return this;
		}
		
		/**
		 * 以len设置向量的长度
		 * @param	len 设置的长度
		 * @return 返回向量自己的引用
		 */
		public function normalcate(len : Number) : Vector2D
		{
			length = len;
			return this;
		}
		
		/**
		 * 如果所给的值小于当前长度, 那么改变长度, 否则将不发生改变
		 * @param	max 向量能够达到的最大长度
		 * @return 本身向量的引用
		 */
		public function truncate(max : Number) : Vector2D
		{
			length = Math.min(max, length);
			return this;
		}
		
		/**
		 * 反方向翻转向量
		 * @return 本身向量的引用
		 */
		public function reverse() : Vector2D
		{
			m_x *= -1;
			m_y *= -1;
			return this;
		}
		
		/**
		 * 计算点积
		 */
		public function dotProduct(vec2 : Vector2D) : Number
		{
			return m_x * vec2.x + m_y * vec2.y;
		}
		
		/**
		 * 计算叉积
		 */
		public function crossProduct(vec2 : Vector2D) : Number
		{
			return m_x * vec2.y - m_y * vec2.x;
		}
		
		/**
		 * 获得与此向量垂直的向量
		 */
		public function get perpendicular() : Vector2D
		{
			return new Vector2D(-m_y, m_x);
		}
		
		/**
		 * 判断指定向量处于本向量的左边还是右边
		 */
		public function sign(vec2 : Vector2D) : int
		{
			return perpendicular.dotProduct(vec2) < 0 ? -1 : 1;
		}
		
		/**
		 * 计算两个向量间的距离
		 */
		public function distance(vec2 : Vector2D) : Number
		{
			return Math.sqrt(distSQ(vec2));
		}
		
		/**
		 * 计算两个向量间距离的平方
		 */
		public function distSQ(vec2 : Vector2D) : Number
		{
			var dx : Number = m_x - vec2.x;
			var dy : Number = m_y - vec2.y;
			return dx * dx + dy * dy;
		}
		
		/**
		 * 加法
		 */
		public function add(vec2 : Vector2D) : Vector2D
		{
			m_x += vec2.x;
			m_y += vec2.y;
			return this;
		}
		
		/**
		 * 减法
		 */
		public function subtract(vec2 : Vector2D) : Vector2D
		{
			m_x -= vec2.x;
			m_y -= vec2.y;
			return this;
		}
		
		/**
		 * 乘法
		 */
		public function mutiply(scalar : Number) : Vector2D
		{
			m_x *= scalar;
			m_y *= scalar;
			return this;
		}
		
		/**
		 * 除法
		 */
		public function divide(scalar : Number) : Vector2D
		{
			m_x /= scalar;
			m_y /= scalar;
			return this;
		}
		
		/**
		 * set/get x
		 */
		public function set x(value : Number) : void
		{
			m_x = value;
		}
		
		public function get x() : Number
		{
			return m_x;
		}
		
		/**
		 * set/get y
		 */
		public function set y(value : Number) : void
		{
			m_y = value;
		}
		
		public function get y() : Number
		{
			return m_y;
		}
		
		/**
		 * 从一个字符串创建一个Vector2D对象
		 * @param	string 字符形式必须是toString()方法返回的形式
		 * @return 根据字符串创建的Vector2D向量
		 */
		public function fromString(string : String) : Vector2D
		{
			var tx : Number = parseFloat(string.substring(string.indexOf("x:"), string.indexOf(",")));
			var ty : Number = parseFloat(string.substring(string.indexOf("y:")));
			return new Vector2D(tx, ty);
		}
		
		/**
		 * 该Vector2D对象的信息
		 * @return 包含该Vector2D向量信息的字符串
		 */
		public function toString() : String
		{
			return "Vector2D x:" + m_x + ", y:" + m_y;
		}
		
		/**
		 * 绘制向量, 指向目标点
		 * @param	graphics 绘制线需要的graphics对象
		 * @param	color 线的颜色
		 */
		public function drawVector(graphics : Graphics, color : uint = 0x00FF00) : void
		{
			graphics.lineStyle(0, color);
			graphics.moveTo(0, 0);
			graphics.lineTo(m_x, m_y);
		}
		
		private var m_x : Number = NaN;
		private var m_y : Number = NaN;
	}

}

































///////////////////////////////////////////////////////////////////////////////////////////////////
// end file


